// ============================== 导入依赖 ============================== //

import dayjs from 'dayjs'
import IS from './is'
import NUM from './num'

// ============================== 导出日期工具 ============================== //

/**
 * 统一的参数格式
 *
 * @param {*} data Date / timestamp / String
 * @param {Number} seconds 间隔秒数 (仅限 now 和 timeXxx 的方法)
 * @param {Number} days 间隔天数
 * @param {Number} months 间隔月数
 * @param {Number} years 间隔年数
 */
export default {
  /**
   * 今天的日期串 / 今天前后间隔的日期串
   */
  today(days = 0, months = 0, years = 0) {
    return getDate('', days, months, years)
  },

  /**
   * 此刻的时间串 / 此刻前后间隔的时间串
   */
  now(seconds = 0, days = 0, months = 0, years = 0) {
    return getTime('', seconds, days, months, years)
  },

  /**
   * 某天的日期串 / 某天前后间隔的日期串
   */
  dateStr(data, days = 0, months = 0, years = 0) {
    return valid(data) ? getDate(data, days, months, years) : ''
  },

  /**
   * 某刻的时间串 / 某刻前后间隔的时间串
   */
  timeStr(data, seconds = 0, days = 0, months = 0, years = 0) {
    return valid(data) ? getTime(data, seconds, days, months, years) : ''
  },

  /**
   * 某刻的 Date 对象 / 某刻前后间隔的 Date 对象
   */
  dateObj(data, seconds = 0, days = 0, months = 0, years = 0) {
    const str = this.timeStr(data, seconds, days, months, years)
    return str ? new Date(str) : null
  },

  /**
   * 某刻的时间戳 / 某刻前后间隔的时间戳
   */
  timeNum(data, seconds = 0, days = 0, months = 0, years = 0) {
    const obj = this.dateObj(data, seconds, days, months, years)
    return obj ? obj.getTime() : 0
  },

  /**
   * 某天的纯中文日期串 / 某天前后间隔的纯中文日期串
   */
  dateCN(data, days = 0, months = 0, years = 0) {
    return valid(data) ? getDateCN(data, days, months, years) : ''
  },

  /**
   * 某刻的纯中文时间串 / 某刻前后间隔的纯中文时间串
   */
  timeCN(data, seconds = 0, days = 0, months = 0, years = 0) {
    return valid(data) ? getTimeCN(data, seconds, days, months, years) : ''
  },

  /**
   * 某刻的周几序号 / 某刻前后间隔的周几序号 (1-7)
   */
  weekNum(data, days = 0, months = 0, years = 0) {
    return valid(data) ? getWeekNum(data, days, months, years) : ''
  },

  /**
   * 某刻的纯中文星期串 / 某刻前后间隔的纯中文星期串
   */
  weekCN(data, days = 0, months = 0, years = 0) {
    return valid(data) ? getWeekCN(data, days, months, years) : ''
  },

  /**
   * 某刻所在周的星期一 / 某刻前后间隔所在周的星期一
   */
  weekMonday(data, days = 0, months = 0, years = 0) {
    return valid(data) ? getWeekMonday(data, days, months, years) : ''
  },

  /**
   * 某刻的月份有多少天 / 某刻前后间隔的月份有多少天
   */
  monthDays(data, months = 0, years = 0) {
    const date = getMonth(valid(data) ? data : '', months, years)
    return date ? new Date(+date.slice(0, 4), +date.slice(5, 7), 0).getDate() : 0 // 下一月的第 0 天
  },
}

// ============================== 内部常量 ============================== //

const FORMAT_DATE = 'YYYY-MM-DD'
const FORMAT_TIME = 'YYYY-MM-DD HH:mm:ss'
const TIMESTAMP = /^\d{5,15}$/
const REGEXP = /^[1-9]\d{3}(-\d\d(-\d\d( \d\d(:\d\d(:\d\d)?)?)?)?)?$/
// YYYY 或 YYYY-MM 或 YYYY-MM-DD 或 YYYY-MM-DD HH 或 YYYY-MM-DD HH:mm 或 YYYY-MM-DD HH:mm:ss

// ============================== 内部方法 ============================== //

/**
 * 是否有效
 *
 * @param {*} data Date / timestamp / String
 *
 * @returns {Boolean} valid
 */
export const valid = (data) => data && (IS.isDate(data) || TIMESTAMP.test(data) || REGEXP.test(data))

/**
 * 获取 dayjs 对象
 *
 * @param {*} data Date / timestamp / String
 * @returns {Object} dayjs
 */
export const getDayjs = (data) => TIMESTAMP.test(data) ? dayjs(+data) : dayjs(data || undefined)

/**
 * 获取日期
 *
 * @param {*}      data Date / timestamp / String
 * @param {Number} days 间隔天数
 * @param {Number} months 间隔月数
 * @param {Number} years 间隔年数
 *
 * @returns {String} FORMAT_DATE
 */
export const getDate = (data, days, months, years) => {
  let obj = getDayjs(data)
  if (+days) obj = obj.add(+days, 'day')
  if (+months) obj = obj.add(+months, 'month')
  if (+years) obj = obj.add(+years, 'year')
  return obj.format(FORMAT_DATE)
}

/**
 * 获取时间
 *
 * @param {*}      data Date / timestamp / String
 * @param {Number} seconds 间隔秒数
 * @param {Number} days 间隔天数
 * @param {Number} months 间隔月数
 * @param {Number} years 间隔年数
 *
 * @returns {String} FORMAT_TIME
 */
export const getTime = (data, seconds, days, months, years) => {
  let obj = getDayjs(data)
  if (+seconds) obj = obj.add(+seconds, 'second')
  if (+days) obj = obj.add(+days, 'day')
  if (+months) obj = obj.add(+months, 'month')
  if (+years) obj = obj.add(+years, 'year')
  return obj.format(FORMAT_TIME)
}

/**
 * 获取中文日期
 */
export const getDateCN = (data, days, months, years) => {
  const str = getDate(data, days, months, years)
  const yearCN = NUM.numYear(str.slice(0, 4))
  const monthCN = NUM.numMonth(str.slice(5, 7))
  const dayCN = NUM.numDay(str.slice(8, 10))
  return `${yearCN}${monthCN}${dayCN}`
}

/**
 * 获取中文时间
 */
export const getTimeCN = (data, seconds, days, months, years) => {
  const str = getTime(data, seconds, days, months, years)
  const hourCN = str.slice(11, 13) ? NUM.numHour(str.slice(11, 13)) : ''
  const minuteCN = str.slice(14, 16) ? NUM.numMinute(str.slice(14, 16)) : ''
  const secondCN = str.slice(17, 19) ? NUM.numSecond(str.slice(17, 19)) : ''
  return `${getDateCN(str)}${hourCN}${minuteCN}${secondCN}`
}

/**
 * 获取周几序号
 */
export const getWeekNum = (data, days, months, years) => {
  const date = getDate(data, days, months, years)
  return dayjs(date).day() || 7
}

/**
 * 获取中文星期
 */
export const getWeekCN = (data, days, months, years) => {
  const week = getWeekNum(data, days, months, years)
  return NUM.numWeek(week)
}

/**
 * 获取所在周的星期一
 */
export const getWeekMonday = (data, days, months, years) => {
  const date = getDate(data, days, months, years)
  const week = dayjs(date)
  const monday = week.day() ? week.day(1) : week.add(-6, 'day')
  return monday.format(FORMAT_DATE)
}

/**
 * 获取月份
 */
export const getMonth = (data, months, years) => {
  let obj = getDayjs(data)
  if (+months) obj = obj.add(+months, 'month')
  if (+years) obj = obj.add(+years, 'year')
  return obj.format(FORMAT_DATE.slice(0, 7))
}
